package com.colabo.j2ee.web.oaf.security.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.ObjectNotFoundException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.Assert;

import com.colabo.j2ee.web.core.common.CommonConstants;
import com.colabo.j2ee.web.core.common.SessionConstants;
import com.colabo.j2ee.web.core.context.ContextUtil;
import com.colabo.j2ee.web.core.dictionary.ICodeInfoService;
import com.colabo.j2ee.web.core.exception.CommonException;
import com.colabo.j2ee.web.core.exception.ServiceException;
import com.colabo.j2ee.web.core.persistence.DateToStringUserType;
import com.colabo.j2ee.web.core.pkgenerator.IPKGenerator;
import com.colabo.j2ee.web.core.servertime.IServerTime;
import com.colabo.j2ee.web.core.service.impl.DefaultServiceImpl;
import com.colabo.j2ee.web.core.util.DateTimeUtil;
import com.colabo.j2ee.web.core.util.PropertyUtil;
import com.colabo.j2ee.web.core.vo.SessionUserHolder;
import com.colabo.j2ee.web.core.vo.RecordObject;
import com.colabo.j2ee.web.oaf.common.AppConstants;
import com.colabo.j2ee.web.oaf.monitorperspective.ILogDataService;
import com.colabo.j2ee.web.oaf.orgnization.IStaffService;
import com.colabo.j2ee.web.oaf.orgnization.model.IPPositionVO;
import com.colabo.j2ee.web.oaf.orgnization.model.SCUserProfileVO;
import com.colabo.j2ee.web.oaf.security.AuthUtil;
import com.colabo.j2ee.web.oaf.security.ICustomUserDetailsService;
import com.colabo.j2ee.web.oaf.security.IGrantService;
import com.colabo.j2ee.web.oaf.security.ISecurityStrategyService;
import com.colabo.j2ee.web.oaf.security.IUserDetailsService;
import com.colabo.j2ee.web.oaf.security.model.AdminAuthorityModel;
import com.colabo.j2ee.web.oaf.security.model.IPArcPasswordHistory;
import com.colabo.j2ee.web.oaf.security.model.ResourceAuthorityModel;
import com.colabo.j2ee.web.oaf.security.model.SCUserSecurityVO;
import com.colabo.j2ee.web.oaf.security.model.UserDetailsModel;
import com.colabo.j2ee.web.oaf.vo.IPAuditLogVO;

public final class UserDetailsServiceImpl extends DefaultServiceImpl implements IUserDetailsService, InitializingBean {
	// Static fields ===================================================
	
	private static final String CHANGE_PASSWORD_OLDPASSWORDERROR = "oldPasswordError";
	private static final String CHANGE_PASSWORD_SUCCESS = "true";
	private static final String CHANGE_PASSWORD_LEN = "nolen";
	private static final String CHANGE_PASSWORD_MODIFIED = "overError";
	private static final String LOCK_TIME_FORMAT = "yyyyMMddHHmmss";

	// Instance fields =================================================
	
	private Log logger = LogFactory.getLog(UserDetailsServiceImpl.class);
	private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
	private ISecurityStrategyService securityStrategyService;
	private IStaffService staffService;
	private IGrantService grantService;
	private ICodeInfoService codeInfoService;
	private ILogDataService logService;
	private SaltSource saltSource;
	private String defaultUserIDColumn;

	// Methods ==========================================================
	
	public PasswordEncoder getPasswordEncoder() {
		return passwordEncoder;
	}

	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
		this.passwordEncoder = passwordEncoder;
	}

	public SaltSource getSaltSource() {
		return saltSource;
	}

	public void setSaltSource(SaltSource saltSource) {
		this.saltSource = saltSource;
	}
	
	public ILogDataService getLogService() {
		return logService;
	}

	public void setLogService(ILogDataService logService) {
		this.logService = logService;
	}

	private ICustomUserDetailsService getCustomUserDetailService() {
		List providers = ContextUtil.getBeansByClass(ICustomUserDetailsService.class);
		if (providers.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("****没有启用自定义ICustomUserDetailsService的实现类****");
			}
			return null;
		} else {
			if (providers.size() > 1) {
				logger.warn("****用户自定义ICustomUserDetailsService的实现类有多个，启用第一个： " + providers.get(0) + "****");
			}
			if (logger.isDebugEnabled()) {
				logger.debug("****启用自定义ICustomUserDetailsService的实现类：" + providers.get(0) + "****");
			}
			return (ICustomUserDetailsService) providers.get(0);
		}
	}

	
	public UserDetails loadUserByUsername(String userSpecifiedID, Object additionalInfo)
			throws UsernameNotFoundException, DataAccessException {
		String userIDColumn = (String) additionalInfo;
		if (logger.isDebugEnabled()) {
			logger.debug("****读取用户信息用于验证："+userSpecifiedID+"/"+userIDColumn+" ****");
		}
		
		UserDetailsModel udModel = new UserDetailsModel();

		/**
		 * 获取数据库中的用户模型，转换为Spring Security中认证用的用户模型
		 */
		SCUserSecurityVO user = null;
		try {
			user = getUserAuthByUsername(userSpecifiedID);
		} catch (ServiceException e) {
			logger.error(e);
		}

		if (user == null) {
			throw new UsernameNotFoundException(userSpecifiedID);
		}

		udModel.setUsername(userSpecifiedID);
		udModel.setPassword(user.getCredential());
		udModel.setAccountNonLocked(!checkAccountLock(user));

		new GrantsThread(udModel, user).start();

		ContextUtil.put("USER_SESSION_INFO", user, ContextUtil.SCOPE_REQUEST);
		return udModel;
	}

	/**
	 * @see org.springframework.security.core.userdetails.UserDetailsService
	 */
	public UserDetails loadUserByUsername(String userSpecifiedID) {
		return this.loadUserByUsername(userSpecifiedID, this.defaultUserIDColumn);
	}

	class GrantsThread extends Thread {
		private UserDetailsModel model;
		private SCUserSecurityVO user;

		public GrantsThread(UserDetailsModel model, SCUserSecurityVO user) {
			this.model = model;
			this.user = user;
		}

		public void run() {
			process(model, user);
		}
	}

	private void process(UserDetailsModel model, SCUserSecurityVO user) {
		try {
			String staffId = user.getUserProfile().getLoginId();

			boolean isAdmin = grantService.isAdmin(staffId);
			if (isAdmin) {
				model.setGod(Boolean.TRUE);
				model.setAuth(Boolean.TRUE);
				return;
			}

			Map para = new HashMap();
			para.put("staffId", staffId);
			List list = find_iBatis("org.getPositionsByStaffId", para);

			if (list == null || list.size() < 1) {
				list = new ArrayList();
			}

			list.add(CommonConstants.PUBLIC_PEMISSION_POSITION_ID);
			String code = list2String(list, "'");

			model.setFuctionAuthorities(grantService.getFunctionList(code));
			model.setUrlAuthorities(grantService.getUrlList(code));
			model.setAuth(true);

		} catch (ServiceException e) {
			logger.error(e);
		}
	}
	
	public SCUserSecurityVO getUserAuthByUsername(String arg0) throws ServiceException {
		if (defaultUserIDColumn == null || defaultUserIDColumn.trim().length() < 1) {
			defaultUserIDColumn = "LOGINID";
		}
		if (arg0 == null) {
			arg0 = "";
		}
		HashMap para = new HashMap();
		para.put("key", defaultUserIDColumn);
		para.put("value", arg0);

		List users = find_iBatis("auth.getUserAuthByUsername", para);
		if (users == null || users.isEmpty()) {
			return null;
		}
		return (SCUserSecurityVO) users.get(0);
	}

	public SCUserSecurityVO getUserAuthByStaff(SCUserProfileVO staff) throws ServiceException {
		if (staff == null) {
			return null;
		}
		List users = find_iBatis("auth.getUserAuthByStaff", staff);
		if (users == null || users.isEmpty()) {
			return null;
		}
		return (SCUserSecurityVO) users.get(0);
	}

	/**
	 * 根据密码出错次数确定账户是否被锁定, 若超过最大出错次数则账户锁定
	 * 若user的getMaxFailedLoginCount为空则取系统安全策略中的最大出错次数
	 * 
	 * @param user
	 * @return
	 */
	private boolean checkAccountLock(SCUserSecurityVO user) {
		Integer flcount = user.getLoginFailedTimes();
		
		SCUserProfileVO userProfile = user.getUserProfile();//获取对应员工
		if ("0".equals(userProfile.getStatus().trim())) {//如果员工状态为锁定，则返回真
			return true;
		}
		if (flcount == null || flcount.intValue()<=0) {//如果错误登录次数为空或小于等于零，则返回未锁定状态
			return false;
		}
		
		int maxLoginCout = securityStrategyService.getMaxFailedLoginCount(userProfile.getLoginId());//获取最大允许错误次数
		if (maxLoginCout == -1) {
			return false;
		}
		return flcount.intValue() >= maxLoginCout;

	}

	protected boolean getNonLocked(Map user) {
		int failedLoginCount = Integer.parseInt(user.get("FAILEDLOGINCOUNT").toString());
		if (failedLoginCount < securityStrategyService.getMaxFailedLoginCount(user.get("staffid").toString()).intValue()) {
			return true;
		}
		return false;
	}

	public List getGrants(SCUserSecurityVO userSecurity) {
		IGrantService grantService = (IGrantService) getBean(IGrantService.BEAN_ID);
		IServerTime serverTime = (IServerTime) getBean(IServerTime.BEAN_ID);

		List grantedResources = null;
		boolean isAdmin = Boolean.FALSE;
		try {
			grantedResources = grantService.getAllGrantsWithRelatedResourceByStaff(userSecurity.getUserProfile(), null, serverTime
					.getServerDateTime());
			isAdmin = grantService.isAdmin(userSecurity.getUserProfile().getLoginId());
		} catch (Exception e) {
			logger.error(e);
			throw new DataAccessException("unable to get grants by username", e) {
				private static final long serialVersionUID = 2312527341423139371L;
			};
		}

		List l = new ArrayList(grantedResources.size());
		for (Iterator it = grantedResources.iterator(); it.hasNext();) {
			l.add(new ResourceAuthorityModel((RecordObject) it.next()));
		}
		if (isAdmin) {
			l.add(new AdminAuthorityModel());
		}
		return l;
	}

	public boolean needChangePassword(String username) throws ServiceException {
		if (username == null) {
			return false;
		}

		ICustomUserDetailsService cuds = getCustomUserDetailService();
		if (cuds != null) {
			return cuds.needChangePassword(username);
		}

		IServerTime serverTime = (IServerTime) getBean(IServerTime.BEAN_ID);
		SCUserSecurityVO userauth = getUserAuthByUsername(username);
		try {
			if (userauth.getPasswordExpireTimestamp() != null) {
				String strDate = userauth.getPasswordExpireTimestamp();
				Date expDate = DateToStringUserType.toDate(strDate, DateToStringUserType.DATA_TO_STRING_FORMATE);
				if (expDate.before(serverTime.getServerDateTime())) {//如果密码过期时间在当前时间之前，表示密码已过期，返回真
					return true;
				}
			}

			// 第一次登录
			String flogin = (String) ContextUtil.get("flogin", ContextUtil.SCOPE_SESSION);
			if ("true".equals(flogin)) {
				if (securityStrategyService.isFirstModifyPwd(username)) {
					return true;
				}
			}
			return false;
		} catch (CommonException e) {
			throw new ServiceException(e);
		}
	}

	/**
	 * 由Spring Security框架调用，做登录认证成功后的业务操作
	 */
	public void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, String username)
			throws ServiceException {
		
		SCUserSecurityVO userSecurityVO;
		userSecurityVO = (SCUserSecurityVO) ContextUtil.get("USER_SESSION_INFO", ContextUtil.SCOPE_REQUEST);

		//如果最近登录时间为空，则设置其首次登陆状态为真，否则设置为空
		if (null == userSecurityVO.getLastLoginTimestamp() || "".equals(userSecurityVO.getLastLoginTimestamp().trim())) {
			ContextUtil.put("flogin", Boolean.TRUE, ContextUtil.SCOPE_SESSION);
		}
		
		
		
		logService.saveLog(IPAuditLogVO.BIZ_TYPE_LOGIN, IPAuditLogVO.OP_CODE_LOGIN, userSecurityVO.getUserProfile().getRealName(), userSecurityVO
				.getLastLoginIpAddress(), PropertyUtil.getPropertyByKey(AppConstants.MSG_INF_APP_0001));
	}

	public void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, String username,
			String pwd, String failed) throws ServiceException {
		ICustomUserDetailsService cuds = getCustomUserDetailService();
		if (cuds != null) {
			cuds.onUnsuccessfulAuthentication(request, response, username);
			return;
		}

		SCUserSecurityVO userauth = getUserAuthByUsername(username);
		if (userauth == null) {
			return;
		}
		// 只有密码错误才更新错误次数并锁定
		Integer failedLoginCount = userauth.getLoginFailedTimes();
		if (failed.indexOf("BadCredentialsException") > 0) {
			userauth.setLoginFailedTimes(new Integer((failedLoginCount == null ? 1 : failedLoginCount.intValue() + 1)));
				
		}
		
		Integer maxFailedLoginCount = securityStrategyService.getMaxFailedLoginCount(userauth.getUserProfile().getLogicalKey());
		userauth.setLoginFailedLimit(maxFailedLoginCount);	
		// 锁定帐户，修改为大于等于的判断，以防登录时修改了安全策略值导致失败次数大于的情况
		failedLoginCount = failedLoginCount == null ? new Integer(0) : failedLoginCount;
		if (failedLoginCount.intValue() >= maxFailedLoginCount.intValue()) {
			SCUserProfileVO ipf = (SCUserProfileVO) findByID_Hibernate_Get(SCUserProfileVO.class, userauth.getUserProfile().getLogicalKey());
			if (ipf != null) {
				ipf.setStatus(SCUserProfileVO.STATUS_INVALIDATE);
//				ipf.set(DateToStringUserType.formatDate(new Date(), LOCK_TIME_FORMAT));
				update_Hibernate_Object(ipf);
			}
		}
		update_Hibernate_Object(userauth);
		
		SCUserProfileVO ipf = userauth.getUserProfile();
		String OpCode = username;
		if(ipf!=null){
			OpCode = ipf.getLogicalKey();
		}
		
		
		logService.saveLog(IPAuditLogVO.BIZ_TYPE_LOGIN, IPAuditLogVO.OP_CODE_LOGIN, OpCode, 
				request.getRemoteAddr(), PropertyUtil.getPropertyByKey(AppConstants.MSG_INFO_APP_2010));
		
		request.getSession().setAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY, username);
		request.getSession().setAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY, pwd);
	}

	public String savePassword(String loginid, String oldPassword, String newPassword) throws ServiceException {
		// 获得当前登录人
		if (loginid == null) {
			loginid = (String) ContextUtil.get("loginid", ContextUtil.SCOPE_SESSION);
		}
		SCUserSecurityVO userauth = getUserAuthByUsername(loginid);
		// 与原密码不匹配
		if (!passwordEncoder.isPasswordValid(userauth.getCredential(), oldPassword, null)) {
			return CHANGE_PASSWORD_OLDPASSWORDERROR;
		}
		String staffid = userauth.getUserProfile().getLogicalKey();
		// 密码长度判断
		if (newPassword.length() < securityStrategyService.getPasswdMinLen(staffid).intValue()) {
			return CHANGE_PASSWORD_LEN;
		}
		// 验证是否与之前的密码重复
		int mdtimes = 0;
		if (securityStrategyService.getPasswordModifiedTimes(staffid) != null) {
			mdtimes = securityStrategyService.getPasswordModifiedTimes(staffid).intValue() - 1;
		}
		HashMap map = new HashMap();
		// map.put("num", String.valueOf(mdtimes));
		map.put("staffid", staffid);
		List history = securityStrategyService.getAllPwdHistory(map);
		if (history.size() > 0 && history != null && mdtimes > 0) {
			for (int i = 0; i < history.size(); i++) {
				IPArcPasswordHistory temp = (IPArcPasswordHistory) history.get(i);
				if (newPassword.equals(temp.getPasswd())) {
					return CHANGE_PASSWORD_MODIFIED;
				}
				if (mdtimes == i + 1) {
					break;
				}
			}
		}
		//重置密码
		String passwd = AuthUtil.encodePassword(newPassword);
		userauth.setPasswd(passwd);
		
		//重置失败次数
		userauth.setFailedLoginCount(new Integer(0));
		
		// 重置失效日期和实效天数
		Integer expDays;
		// 取全局变量 expDays = userauth.getPasswdExpireDays().intValue();
		expDays = securityStrategyService.getPasswordExpireDays(loginid);
		String temp = DateToStringUserType.formatDate(new Date(), DateToStringUserType.DATA_TO_STRING_FORMATE);
		// Date today = DateTimeUtil.getDate();
		Date today = DateToStringUserType.toDate(temp, DateToStringUserType.DATA_TO_STRING_FORMATE);
		Date expDate = DateTimeUtil.addDay(today, expDays.intValue());
		String tempExp = DateToStringUserType.formatDate(expDate, DateToStringUserType.DATA_TO_STRING_FORMATE);
		// userauth.setPasswdExpireDays(expDays);
		userauth.setPasswdExpireTime(tempExp);
		
		//设置最后登录时间
		if (userauth.getLastLoginTimestamp() == null || "".equals(userauth.getLastLoginTimestamp())) {
			if (userauth.getLoginTime() == null || "".equals(userauth.getLoginTime())) {
				userauth.setLoginTime(temp);
				userauth.setLastLoginTime(temp);
			} else {
				userauth.setLastLoginTime(userauth.getLoginTime());
			}
		}
		
		//修改对应的员工密码
		try {
			// SCUserProfileVO vo = (SCUserProfileVO)
			// this.findByID_Hibernate_Get(SCUserProfileVO.class, staffid);
			SCUserProfileVO vo = staffService.getStaffByStaffId(staffid);
			vo.setPassWord(passwd);
			String loginName = null;
			if (vo != null) {
				loginName = vo.getLoginName();
			}

			//String isSyn = codeInfoService.getCodeInfoVOByInfoCode("SystemConfiguration", "getLDAPData")
			//		.getCodeinfoValue();
			if ("y".equals(vo.getIsSyn())) {
				synService.setUserPassword(loginName, newPassword);// 将密码同步到Ldap中
			}
			update_Hibernate_Object(vo);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new ServiceException(ex);
		}

		update_Hibernate_Object(userauth);//修改用户对象
		
		
		//在历史密码表中保留原始密码记录
		IPKGenerator keyGen = (IPKGenerator) getBean(IPKGenerator.BEAN_ID);
		IPArcPasswordHistory pwdHistVo = new IPArcPasswordHistory();
		pwdHistVo.setPwdhistky(keyGen.getUUIDKey(pwdHistVo));
		// 谁更改的密码
		pwdHistVo.setUpdateStaffId(staffid);
		// 更改了谁的密码
		pwdHistVo.setStaffid(staffid);
		// pwdHistVo.setUser(userauth);
		pwdHistVo.setPasswd(oldPassword);
		// pwdHistVo.setUpdateUser(userauth);
		pwdHistVo.setUpdateTime(temp);
		save_Hibernate_Object(pwdHistVo);
		return CHANGE_PASSWORD_SUCCESS;
	}

	public List query(Map params, int offset, int pageSize) throws ServiceException {
		return find_iBatis("auth.queryUser", params, offset, pageSize);
	}

	public int queryCount(Map params) throws ServiceException {
		List l = find_iBatis("auth.queryUserCount", params);
		if (l != null && !l.isEmpty()) {
			return ((Integer) l.get(0)).intValue();
		}
		return 0;
	}

	public void batchCommit(List insertBeans, List updateBeans, List delBeans) throws ServiceException {
		String passwd = "";
		if (insertBeans != null) {
			for (Iterator it = insertBeans.iterator(); it.hasNext();) {
				SCUserSecurityVO arcuser = (SCUserSecurityVO) it.next();

				passwd = arcuser.getCredential();
				if (passwd == null || passwd.length() < 1) {
					passwd = securityStrategyService.getDefaultPasswd(arcuser.getUserProfile().getLogicalKey());
				}

				SCUserProfileVO vo = (SCUserProfileVO) findByID_Hibernate_Load(SCUserProfileVO.class, arcuser.getUserProfile().getLogicalKey());
				vo.setPassWord(passwd);
				staffService.addStaff(vo);
			}
		}

		if (updateBeans != null) {
			for (Iterator it = updateBeans.iterator(); it.hasNext();) {
				SCUserSecurityVO arcuser = (SCUserSecurityVO) it.next();
				passwd = securityStrategyService.getDefaultPasswd(arcuser.getUserProfile().getLogicalKey());
				passwd = AuthUtil.encodePassword(passwd);
				arcuser.setPasswd(passwd);
				update(arcuser);

				try {
					SCUserProfileVO vo = (SCUserProfileVO) findByID_Hibernate_Load(SCUserProfileVO.class, arcuser.getUserProfile().getLogicalKey());
					vo.setPassWord(passwd);
					save_Hibernate_Object(vo);
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		}

		if (delBeans != null) {
			for (Iterator it = delBeans.iterator(); it.hasNext();) {
				delete((SCUserSecurityVO) it.next());
			}
		}
	}
	
	/**
	 * 批量修改人员状态
	 * @param updateBeans
	 * @throws ServiceException
	 */
	public void batchCommitState(List updateBeans) throws ServiceException {
		if (updateBeans != null) {
			for (Iterator it = updateBeans.iterator(); it.hasNext();) {
				SCUserSecurityVO arcuser = (SCUserSecurityVO) it.next();
				update(arcuser);
			}
		}
	}
	
	/**
	 * 与batchCommit方法的区别是，batchCommit方法选取的密码为默认密码，此方法选取的密码为前台设置的密码
	 * @param insertBeans
	 * @param updateBeans
	 * @param delBeans
	 * @throws ServiceException
	 */
	public void batchCommitByDs(List insertBeans, List updateBeans, List delBeans) throws ServiceException {
		String passwd = "";
		if (insertBeans != null) {
			for (Iterator it = insertBeans.iterator(); it.hasNext();) {
				SCUserSecurityVO arcuser = (SCUserSecurityVO) it.next();

				//如果设置的密码不存在，则取默认密码
				passwd = arcuser.getCredential();
				if (passwd == null || passwd.length() < 1) {
					passwd = AuthUtil.encodePassword(
							securityStrategyService.getDefaultPasswd(arcuser.getUserProfile().getLogicalKey()));
				}
				
				SCUserProfileVO vo = (SCUserProfileVO) findByID_Hibernate_Load(SCUserProfileVO.class, arcuser.getUserProfile().getLogicalKey());
				vo.setPassWord(passwd);
				staffService.addStaff(vo);//添加员工
			}
		}

		if (updateBeans != null) {
			for (Iterator it = updateBeans.iterator(); it.hasNext();) {
				SCUserSecurityVO arcuser = (SCUserSecurityVO) it.next();
				
				//如果设置的密码不存在，则取默认密码
				passwd = arcuser.getCredential();
				if (passwd == null || passwd.length() < 1) {
					passwd = AuthUtil.encodePassword(
							securityStrategyService.getDefaultPasswd(arcuser.getUserProfile().getLogicalKey()));
				}
				
				arcuser.setPasswd(passwd);
				arcuser.setFailedLoginCount(new Integer(0));//将登录用户对象的登录失败次数初始为0
				arcuser.setPasswdExpireTime(null);//重新设置登录用户对象的密码过期时间,checkUser方法中会根据当前时间和密码有效期天数重新计算密码过期时间
				update(arcuser);//修改用户

				try {
					SCUserProfileVO vo = (SCUserProfileVO) findByID_Hibernate_Load(SCUserProfileVO.class, arcuser.getUserProfile().getLogicalKey());
					vo.setPassWord(passwd);//修改对应员工密码
					//save_Hibernate_Object(vo);
					staffService.save(vo);//保存员工对象
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		}

		if (delBeans != null) {
			for (Iterator it = delBeans.iterator(); it.hasNext();) {
				delete((SCUserSecurityVO) it.next());
			}
		}
	}

	private void checkUser(SCUserSecurityVO user, String oldPassword) throws ServiceException {
		IServerTime serverTime = (IServerTime) getBean(IServerTime.BEAN_ID);
		if (user.getUserProfile() == null) {
			throw new ServiceException("");
		}

		if (user.getUserProfile().getLogicalKey() == null || "".equals(user.getUserProfile().getLogicalKey())) {
			throw new ServiceException("");
		}

		//如果设置的密码不存在，则从安全策略中取默认密码
		if (user.getCredential() == null) {
			// 若在DaoAuthenticationProvider中配置了saltSource, 比较结果可能会不一样passwordEncoder.encodePassword
			user.setPasswd(AuthUtil.encodePassword(securityStrategyService.getDefaultPasswd(user.getUserProfile().getLogicalKey()),
					null));
		}

		//如果“最大允许密码失败次数”为空，则从安全策略中取所设置的最大允许密码失败次数
		if (user.getMaxFailedLoginCount() == null) {
			user.setMaxFailedLoginCount(securityStrategyService.getMaxFailedLoginCount(user.getUserProfile().getLogicalKey()));
		}

		//如果“密码有效期”为空，则从安全策略中取所设置的密码有效期
		if (user.getPasswdExpireDays() == null) {
			user.setPasswdExpireDays(securityStrategyService.getPasswordExpireDays(user.getUserProfile().getLogicalKey()));
		}

		//如果密码有效期为－1，表示不限制密码的过期，则将密码过期时间设置为空
		if (user.getPasswdExpireDays().intValue() == SCUserSecurityVO.EXPIRE_DAYS_NEVER_EXPIRE) {
			user.setPasswdExpireTime(null);
		} 
		//如果密码有效期不为－1，且密码过期时间为空，则重新设置密码过期时间为当前系统时间加上密码有效期后的日期
		else if (user.getPasswordExpireTimestamp() == null) {
			Calendar c = Calendar.getInstance();
			try {
				c.setTime(serverTime.getServerDateTime());
			} catch (CommonException e) {
				throw new ServiceException(e);
			}
			c.add(Calendar.DAY_OF_MONTH, user.getPasswdExpireDays().intValue());
			String dateNow = DateToStringUserType.formatDate(c.getTime(), DateToStringUserType.DATA_TO_STRING_FORMATE);
			user.setPasswdExpireTime(dateNow);
		}

		//如果删除状态为空，则将删除状态设置为正常状态
		if (user.getDelFlag() == null) {
			user.setDelFlag(SCUserSecurityVO.DEL_FLAG_NORMAL);
		}
	}

	public SCUserSecurityVO save(SCUserSecurityVO user) throws ServiceException {
		IPKGenerator keyGen = (IPKGenerator) getBean(IPKGenerator.BEAN_ID);
		checkUser(user, null);
		user.setUserauthky(keyGen.getUUIDKey(user));
		save_Hibernate_Object(user);

		return user;
	}

	public SCUserSecurityVO update(SCUserSecurityVO user) throws ServiceException {
		SCUserSecurityVO oldUser = (SCUserSecurityVO) findByID_Hibernate_Get(SCUserSecurityVO.class, user.getUserauthky());
		checkUser(user, oldUser.getCredential());
		update_Hibernate_Object(user);
		return user;
	}

	public void delete(SCUserSecurityVO user) throws ServiceException {
		deleteByID_Hibernate_Object(SCUserSecurityVO.class, user.getUserauthky());
	}

	public String getAuthTableField() {
		return defaultUserIDColumn;
	}

	public void setAuthTableField(String defaultUserIDColumn) {
		this.defaultUserIDColumn = defaultUserIDColumn;
	}

	public List queryAuthUser(Map params, int offset, int pageSize) throws ServiceException {
		return find_iBatis("auth.queryAuthUser", params, offset, pageSize);
	}

	public int queryAuthUserCount(Map params) throws ServiceException {
		List l = find_iBatis("auth.queryAuthUserCount", params);
		if (l != null && !l.isEmpty()) {
			return ((Integer) l.get(0)).intValue();
		}
		return 0;
	}

	public ISecurityStrategyService getSecurityStrategyService() {
		return securityStrategyService;
	}

	public void setSecurityStrategyService(ISecurityStrategyService securityStrategyService) {
		this.securityStrategyService = securityStrategyService;
	}

	public IStaffService getStaffService() {
		return staffService;
	}

	public void setStaffService(IStaffService staffService) {
		this.staffService = staffService;
	}

	public IGrantService getGrantService() {
		return grantService;
	}

	public void setGrantService(IGrantService grantService) {
		this.grantService = grantService;
	}

	/**
	 * 列表转换成字符串
	 * 
	 * @param list
	 * @param space
	 * @return
	 */
	private static String list2String(List list, String space) {
		if (null == list || list.size() < 1) {
			return "";
		}
		StringBuffer sb = new StringBuffer();
		int count = list.size();

		if (null == space || space.length() < 1) {
			for (int i = 0; i < count; i++) {
				sb.append(list.get(i));
				sb.append(",");
			}
		} else {
			for (int i = 0; i < count; i++) {
				sb.append(space);
				sb.append(list.get(i));
				sb.append(space);
				sb.append(",");
			}
		}
		sb.deleteCharAt(sb.length() - 1);

		return sb.toString();
	}
	
	/**
	 * 定时解锁用户
	 */
	public void unlockStaff() throws ServiceException {
		try {
			//查找为锁定状态的人员
			HashMap map = new HashMap();
			map.put("status", SCUserProfileVO.STATUS_INVALIDATE);
			List updateList = staffService.query(map, 0, 999999);
			
			for (int i = 0; i < updateList.size(); i++) {
				SCUserProfileVO staff = (SCUserProfileVO) updateList.get(i);
				String locktime = staff.getLockTime();
				int autoEnableTime = securityStrategyService.getAutoEnableTime(staff.getLogicalKey()).intValue();
				
				//如果人员锁定时间没有，则认为立即修改
				if(locktime == null ){
					staff.setStatus(SCUserProfileVO.STATUS_VALIDATE);//修改人员状态
					staffService.save(staff);//保存员工对象
					
					SCUserSecurityVO auth = getUserAuthByStaff(staff);

					// 如果为锁定，则将 登录失败次数 修改为 最大允许失败次数，如果为解锁，则设置为0
					auth.setFailedLoginCount(new Integer("0"));
					update_Hibernate_Object(auth);
				}else{
					Date lockdate = DateToStringUserType.toDate(locktime, LOCK_TIME_FORMAT);
					Calendar cal = Calendar.getInstance();
					cal.setTime(lockdate);
					cal.add(Calendar.HOUR, autoEnableTime);
					
					//如果锁定时间加上解锁时间在当前时间之后，说明还未到解锁的时候，则跳过,如果autoEnableTime为－1，表示不控制，即时解锁
					if(autoEnableTime!=-1 && cal.getTime().after(new Date())){
						continue;
					}
					staff.setLockTime(null);
					staff.setStatus(SCUserProfileVO.STATUS_VALIDATE);//修改人员状态
					staffService.save(staff);//保存员工对象
					
					SCUserSecurityVO auth = getUserAuthByStaff(staff);

					// 如果为锁定，则将 登录失败次数 修改为 最大允许失败次数，如果为解锁，则设置为0
					auth.setFailedLoginCount(new Integer("0"));
					update_Hibernate_Object(auth);
				}
				
			}
			
			//staffService.batchCommit(null, aList, null);// 批量修改员工状态
			//batchCommitState(updateListAuth);

		} catch (ServiceException e) {
			logger.error(e.getXMLStackTraceString(e));
			return;
		} catch (CommonException e) {
			logger.error(e.getXMLStackTraceString(e));
			return;
		}
	}
	
	public List getAuthOrgList(String staffid) throws ServiceException {
		 List authOrgList = getAuthOrgList(staffid);
		return authOrgList;
	} 

	public ICodeInfoService getCodeInfoService() {
		return codeInfoService;
	}

	public void setCodeInfoService(ICodeInfoService codeInfoService) {
		this.codeInfoService = codeInfoService;
	}

	public void afterPropertiesSet() throws Exception {
		Assert.notNull(this.defaultUserIDColumn, "defaultUserIDColumn must not be null!");
		Assert.notNull(this.staffService, "staffService must not be null!");
		Assert.notNull(this.grantService, "grantService must not be null!");
		Assert.notNull(this.logService, "logService must not be null!");
		Assert.notNull(this.codeInfoService, "codeInfoService must not be null!");
		if (this.passwordEncoder instanceof PlaintextPasswordEncoder) {
			logger.warn("your password will not be encoded!");
		}
	}
}
